#include "../logs/log.hpp"
#include <vector>
#include <thread>
#include <chrono>

void bench(const std::string& logger_name, size_t thread_num, size_t msg_count, size_t msg_len)
{
    // 1. 获取日志器
    Mylog::Logger::ptr logger = Mylog::getLogger(logger_name);
    if(logger == nullptr)
        return;
    //2. 组织指定长度的日志消息字符串
    std::string message(msg_len - 1, 'A'); // 预留一个空间存放换行符

    std::cout << "测试开始:\t 日志条数： " << msg_count << ", 总大小: " << (msg_count * msg_len / 1024) << "KB\n";

    // 3. 创建指定数目线程
    std::vector<std::thread> threads;
    size_t msg_ptr_thr = msg_count / thread_num; // 每个线程负责输出的日志数量
    std::vector<double> cost_array(thread_num); // 存放每个线程处理任务耗时
    for(int i = 0; i < thread_num; i++)
    {
        threads.emplace_back([&, i](){
            // 4. 线程内部开始计时
            auto begin = std::chrono::high_resolution_clock::now();
            // 5. 开始循环写日志
            for(size_t j = 0; j < msg_ptr_thr; j++)
            {
                logger->info("%s\n", message.c_str());
            }
            // 6. 线程函数内部结束计时
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> time_span = end - begin;
            cost_array[i] = time_span.count();

            std::cout << "线程" << i << ":\t 输出日志数量：" << msg_ptr_thr << " , 耗时: " << time_span.count() << "s\n";
        });
    }

    for(int i = 0; i < thread_num; i++)
        threads[i].join();
    
    // 7. 总耗时
    double max_cost = 0.0;
    for(int i = 0; i < thread_num; i++) max_cost = max_cost < cost_array[i] ? cost_array[i] : max_cost;
    // 8. 各项测试结果
    size_t msg_per_sec = msg_count / max_cost;
    size_t size_per_sec = (msg_count * msg_len )/ (max_cost * 1024);

    std::cout << "压测结果\t";
    std::cout << "总耗时:" << max_cost << "s\n";
    std::cout << "每秒日志输出数量: " << msg_per_sec << std::endl;
    std::cout << "每秒日志输出大小: " << size_per_sec << "KB\n";
}

void syc_bench()
{
    std::unique_ptr<Mylog::LoggerBuilder> bulider(new Mylog::GlobalLoggerBuilder());
    bulider->bulidLoggerName("sync_logger");
    bulider->bulidLoggerType(Mylog::LoggerType::LOGGER_SYNC);
    bulider->bulidFormatter("%m%n");
    bulider->buildSink<Mylog::FileSink>("./logfile/sync.log");
    bulider->build();
    bench("sync_logger", 3, 1000000, 100);
}


void asyc_bench()
{
    std::unique_ptr<Mylog::LoggerBuilder> bulider(new Mylog::GlobalLoggerBuilder());
    bulider->bulidLoggerName("async_logger");
    bulider->bulidLoggerType(Mylog::LoggerType::LOGGER_ASYNC);
    bulider->buildEnableUnsafeAsync(); // 非安全模式，排除实际落地时间
    bulider->bulidFormatter("%m%n");
    bulider->buildSink<Mylog::FileSink>("./logfile/async.log");
    bulider->build();
    bench("async_logger", 4, 2000000, 100);
}


int main()
{
    asyc_bench();
    return 0;
}